const path = require('path')
const fs = require('fs')

const jwt = require('jsonwebtoken')
const { JWT_SECRET } = require('../config/config.default')
const { Op } = require("sequelize")

const { formatDate } = require('../utils/formatData')
const { userAddError, userModifyError, userDeleteHimSelfError, userDeleteError } = require('../constant/err.type')
const {
    createUser,
    getUserInfo,
    getUserList,
    modifyByUserAccount,
    deleteByUserAccount
} = require('../service/user.service')

const { getRoleInfo } = require('../service/role.service')

const { createAttention, getAttentionActList, isAttention, cancelAttention } = require('../service/userAttentionAct.service')

const { getACtDetailById, } = require('../service/activity.service')

class UserController {
    /**
     * 批量注册
     */
    async batchRegister (ctx, next) {
        const { batchLoginList } = ctx.request.body
        let batchList = JSON.parse(batchLoginList)
        // 写入数据
        try {
            let sign = true
            for (let item of batchList) {
                const res = await createUser({ user_account: item.userAccount, user_name: item.userName, password: item.password, role: 'student' })
                if (res.errorFlag) {
                    sign = false
                }
            }
            if (sign) {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '批量注册成功',
                    data: ''
                }
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: false,
                    code: 20000,
                    message: '注册失败',
                    data: ''
                }
            }

        } catch (error) {
            console.error('批量注册失败', error)
            ctx.app.emit('error', userAddError, ctx)
            return
        }
    }

    /**
     * 新增(注册)用户
     */
    async addUser (ctx, next) {
        const { userAccount, userName, password, role, userTel } = ctx.request.body
        // 写入数据
        try {
            const res = await createUser({ user_account: userAccount, user_name: userName, password, role, user_tel: userTel })
            if (res.errorFlag) {
                console.error('注册失败，数据库新增数据错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '用户注册成功',
                    data: {
                        id: res.id,
                        userName: res.user_name
                    }
                }
            }
        } catch (error) {
            console.error('注册失败', error)
            ctx.app.emit('error', userAddError, ctx)
            return
        }
    }

    /**
     * 用户登录
     */
    async login (ctx, next) {
        const { userAccount } = ctx.request.body
        // 1. 获取用户信息(在token的payload中要记录id、user_account)
        try {
            const res = await getUserInfo({ user_account: userAccount })
            const userDataValues = res[0].dataValues
            ctx.status = 200
            ctx.body = {
                hasOk: true,
                code: 20000,
                message: '用户登录成功',
                data: {
                    id: res.id,
                    // jwt.sign(载荷[加密的内容]，加密的秘钥，过期时间)
                    token: jwt.sign({ userAccount: userDataValues.user_account, role: userDataValues.role }, JWT_SECRET, { expiresIn: '6h' })
                }
            }
        } catch (error) {
            console.error('登录失败', error)
            ctx.app.emit('error', userLoginError, ctx)
            return
        }
    }

    /**
     * 微信登录
     */
    async wxlogin (ctx, next) {
        const { userAccount, openid } = ctx.request.body
        // 1. 获取用户信息(在token的payload中要记录id、user_account)
        try {
            await modifyByUserAccount({ openid }, userAccount)
            const res = await getUserInfo({ user_account: userAccount })
            const userDataValues = res[0].dataValues
            ctx.status = 200
            ctx.body = {
                hasOk: true,
                code: 20000,
                message: '用户登录成功',
                data: {
                    id: res.id,
                    // jwt.sign(载荷[加密的内容]，加密的秘钥，过期时间)
                    token: jwt.sign({ userAccount: userDataValues.user_account, role: userDataValues.role }, JWT_SECRET, { expiresIn: '6h' })
                }
            }
        } catch (error) {
            console.error('登录失败', error)
            ctx.app.emit('error', userLoginError, ctx)
            return
        }
    }

    /**
     * 用户登出(注销)
     */
    async logout (ctx, next) {
        ctx.status = 200
        ctx.body = {
            hasOk: true,
            code: 20000,
            message: '用户登出成功',
            data: {}
        }
    }

    /**
     * 获取用户信息
     */
    async getUserInfo (ctx, next) {
        try {
            // 1. 获取用户信息(id、user_account、role、avatar、user_tel、user_name)
            const { userAccount } = ctx.state.token
            const userRes = await getUserInfo({ user_account: userAccount })
            const userDataValues = userRes[0].dataValues
            const roleRes = await getRoleInfo({ role_code: userDataValues.role })
            const roleDataValues = roleRes[0].dataValues
            ctx.body = {
                hasOk: true,
                code: 20000,
                data: {
                    userId: userDataValues.id,
                    userName: userDataValues.user_name,
                    userAccount: userDataValues.user_account,
                    userTel: userDataValues.user_tel,
                    roleCode: roleDataValues.role_code,
                    roleName: roleDataValues.role_name,
                    avatar: userDataValues.avatar,
                }
            }
        } catch (error) {
            console.log(error)
        }
    }

    /**
     * 获取用户列表
     */
    async getUserList (ctx, next) {
        const { userName: user_name, userAccount: user_account, role: role, userTel: user_tel, isActive: is_active } = ctx.query
        let { limit, offect } = ctx.query
        offect = limit * offect - limit
        const whereOpt = {}
        // 短路运算 值存在就拷贝进whereOpt 
        // [Op.substring] 为模糊查询
        user_name && Object.assign(whereOpt, { user_name: { [Op.substring]: user_name } })
        user_account && Object.assign(whereOpt, { user_account: { [Op.substring]: user_account } })
        role && Object.assign(whereOpt, { role })
        user_tel && Object.assign(whereOpt, { user_tel: { [Op.substring]: user_tel } })
        is_active && Object.assign(whereOpt, { is_active })

        const { count, rows } = await getUserList(whereOpt, offect, limit)
        let resList = []
        for (let item of rows) {
            const roleRes = await getRoleInfo({ role_code: item.role })
            const roleDataValues = roleRes[0].dataValues
            let tempObj = {}
            tempObj.id = item.id
            tempObj.userAccount = item.user_account
            tempObj.userName = item.user_name
            tempObj.isActive = item.is_active
            tempObj.userTel = item.user_tel
            tempObj.password = item.password
            tempObj.avatar = item.avatar
            tempObj.role = item.role
            tempObj.roleName = roleDataValues.role_name
            tempObj.createdAt = item.createdAt
            tempObj.updatedAt = item.updatedAt
            resList.push(tempObj)
        }
        ctx.body = {
            hasOk: true,
            code: 20000,
            data: {
                resList,
                count
            }
        }
    }

    /**
     * 修改用户信息
     */
    async modifyInfoByUserAccount (ctx, next) {
        const { userAccount, userName: user_name, userTel: user_tel, role } = ctx.request.body
        try {
            const res = await modifyByUserAccount({ user_name, user_tel, role }, userAccount)
            if (res.errorFlag) {
                console.error('修改失败，数据库错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '用户信息修改成功',
                    data: ''
                }
            }
        } catch (error) {
            console.error('数据修改失败', error)
            ctx.app.emit('error', userModifyError, ctx)
            return
        }
    }

    /**
     * 修改密码
     */
    async modifyPwd (ctx, next) {
        const { userAccount, password } = ctx.request.body
        try {
            const res = await modifyByUserAccount({ password: password }, userAccount)
            if (res.errorFlag) {
                console.error('修改失败，数据库错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '密码修改成功',
                    data: ''
                }
            }
        } catch (error) {
            console.error('密码修改失败', error)
            ctx.app.emit('error', userModifyError, ctx)
            return
        }
    }

    /**
    * 根据user_account删除一个用户
    */
    async deleteUser (ctx, next) {
        const { userAccount } = ctx.request.body
        if (ctx.state.token.userAccount === userAccount) {
            console.error('密码修改失败,不能删除自己', ctx.request.body)
            ctx.app.emit('error', userDeleteHimSelfError, ctx)
            return
        }
        try {
            const userRes = await getUserInfo({ user_account: userAccount })
            const userDataValues = userRes[0].dataValues
            const res = await deleteByUserAccount(userAccount)
            if (res.errorFlag) {
                console.error('删除失败，数据库错误', res.message)
                ctx.status = 500
            } else {
                // 寻找旧头像的路径，如果是defaultAvatar.gif，则不删除
                if (userDataValues.avatar !== 'avatar/defaultAvatar.gif') {
                    // 删除旧的头像
                    const OldAvatarPath = path.join(__dirname, `../public/upload/${userDataValues.avatar}`)
                    fs.unlink(OldAvatarPath, (err) => {
                        if (err) {
                            // 找不到旧图像路径
                            console.error('找不到图像路径', err)
                        }
                    })
                }
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '删除成功',
                    data: { userAccount }
                }
            }
        } catch (error) {
            console.error('用户删除失败', error)
            ctx.app.emit('error', userDeleteError, ctx)
            return
        }
    }
    /**
     * 头像上传
     */
    async uploadAvatar (ctx, next) {
        try {
            const { userAccount } = ctx.request.body
            const avatar = ctx.state.avatar

            const oldUserRes = await getUserInfo({ user_account: userAccount })
            const oldUserDataValues = oldUserRes[0].dataValues
            try {
                const res = await modifyByUserAccount({ avatar }, userAccount)
                if (res.errorFlag) {
                    console.error('修改失败，数据库错误', res.message)
                    ctx.status = 500
                } else {
                    //  头像上传后，删除旧头像
                    // 寻找旧头像的路径，如果是defaultAvatar.gif，则不删除
                    if (oldUserDataValues.avatar !== 'avatar/defaultAvatar.gif') {
                        // 删除旧的头像
                        const OldAvatarPath = path.join(__dirname, `../public/upload/${oldUserDataValues.avatar}`)
                        fs.unlink(OldAvatarPath, (err) => {
                            if (err) {
                                // 找不到旧图像路径
                                console.error('旧头像删除失败', err)
                            }
                        })
                    }
                    ctx.status = 200
                    ctx.body = {
                        hasOk: true,
                        code: 20000,
                        message: '用户头像修改成功',
                        data: ''
                    }
                }
            } catch (error) {
                console.error('数据修改失败', error)
                ctx.app.emit('error', userModifyError, ctx)
                return
            }
        } catch (error) {
            console.log(error)
        }
    }

    /**
     * 更改用户账号激活状态
     */
    async modifyAccountActiveStatus (ctx, next) {
        const { userAccount, isActive } = ctx.request.body
        try {
            const res = await modifyByUserAccount({ is_active: isActive }, userAccount)
            if (res.errorFlag) {
                console.error('修改失败，数据库错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '账号状态修改成功',
                    data: { userAccount, isActive }
                }
            }
        } catch (error) {
            console.error('账号状态修改失败', error)
            ctx.app.emit('error', userModifyError, ctx)
            return
        }
    }

    /**
     * 关注活动
     */
    async attentionACT (ctx, next) {
        const { userAccount, actId } = ctx.request.body
        const { count } = await isAttention({ user_account: userAccount, act_id: actId })
        if (count) {
            ctx.status = 200
            ctx.body = {
                hasOk: true,
                code: 20000,
                message: '已关注',
                data: ''
            }
        } else {
            await createAttention({ user_account: userAccount, act_id: actId })
            ctx.status = 200
            ctx.body = {
                hasOk: true,
                code: 20000,
                message: '用户关注成功',
                data: ''
            }
        }
    }

    /**
     * 获取关注列表
     */
    async getAttentionActList (ctx, next) {
        const { userAccount } = ctx.query
        const res = await getAttentionActList({ user_account: userAccount })
        if (res.errorFlag) {
            console.error('关注列表获取失败失败，数据库错误', res.message)
            ctx.status = 500
        } else {
            let resList = []
            for (let item of res) {
                let tempObj = {}
                const actRes = await getACtDetailById(item.act_id)
                tempObj.actId = item.act_id
                tempObj.userAccount = item.user_account
                tempObj.startTime = formatDate(Date.parse(actRes.start_time))
                tempObj.organizerAccount = actRes.organizer_account

                const organizerRes = await getUserInfo({ user_account: actRes.organizer_account })
                const organizerDataValues = organizerRes[0].dataValues
                tempObj.organizerName = organizerDataValues.user_name

                tempObj.actTitle = actRes.act_title
                tempObj.imgPath = []
                resList.push(tempObj)
            }

            ctx.status = 200
            ctx.body = {
                hasOk: true,
                code: 20000,
                message: '关注列表获取成功',
                data: resList
            }
        }
    }

    /**
     * 判断用户是否已关注该活动
     */
    async isAttention (ctx, next) {
        const { userAccount, actId } = ctx.request.query
        const { count } = await isAttention({ user_account: userAccount, act_id: actId })
        ctx.status = 200
        ctx.body = {
            hasOk: true,
            code: 20000,
            data: count
        }
    }

    /**
     * 取消关注
     */
    async cancelAttention (ctx, next) {
        const { userAccount, actId } = ctx.request.body
        const res = await cancelAttention({ user_account: userAccount, act_id: actId })
        ctx.status = 200
        ctx.body = {
            hasOk: true,
            code: 20000,
            message: '已取消关注该活动',
            data: ''
        }
    }

    /**
     * 判断用户是否存在
     */
    async userIsExistController (ctx, next) {
        ctx.status = 200
        ctx.body = {
            hasOk: true,
            code: 20000,
            message: '用户存在',
            data: ''
        }
    }
}

module.exports = new UserController()